
/*
 * Copyright (c) 2009, Hamish Morgan. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the University of Sussex nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package piccat.diamondtouch;

import java.awt.Point;
import java.awt.Rectangle;

/**
 * Class for holding information about a single "bounding box" OSC message
 * from DTBridge and DiamondTouch table. This denotes the smallest bounding
 * box containing all the table contacts for the specified user.
 *
 * Protocol:
 *
 * String:      name    (/DTBoundingBox)
 * Integer:     table width   (eg 2032)
 * Integer:     table height  (eg 1520)
 * Integer:     userId  (0...7)
 * String:      action  [up|down|move]
 * Integer:     xOrigin (0 <= xOrigin <= xCorner)
 * Integer:     yOrigin (0 <= yOrigin <= yCorner)
 * Integer:     xCorner (0 <= xCorner <= width)
 * Integer:     yCorner (0 <= xCorner <= height)
 *
 * @author Hamish Morgan
 */
public class DTBoundingBoxEvent extends DTEvent {

    public enum Action {

        UP, DOWN, MOVE
    }
    private final Action action;
    private final int xOrigin;
    private final int yOrigin;
    private final int xCorner;
    private final int yCorner;

    public DTBoundingBoxEvent(DTHandler source, int userId, long time,
            Action action, int xOrigin, int yOrigin, int xCorner, int yCorner)
            throws IllegalArgumentException {
        super(source, userId, time);
//        if (xOrigin < 0 || xOrigin > xCorner)
//            throw new IllegalArgumentException(
//                    "X-Origin should be an integer between 0 and X-Corner (" +
//                    +yCorner + ") inclusive, but found " + xOrigin);
//        if (yOrigin < 0 || yOrigin > yCorner)
//            throw new IllegalArgumentException(
//                    "Y-Origin should be an integer between 0 and Y-Corner (" +
//                    +yCorner + ") inclusive, but found " + yOrigin);
        this.action = action;
        this.xOrigin = xOrigin;
        this.yOrigin = yOrigin;
        this.xCorner = xCorner;
        this.yCorner = yCorner;
    }

    protected DTBoundingBoxEvent(DTHandler source, int userId, long time,
            String action, int xOrigin, int yOrigin, int xCorner, int yCorner)
            throws IllegalArgumentException {
        this(source, userId, time, Action.valueOf(action.toUpperCase()),
                xOrigin, yOrigin, xCorner, yCorner);
    }

    protected DTBoundingBoxEvent(DTBoundingBoxEvent other) throws
            IllegalArgumentException {
        super(other);
        this.xOrigin = other.xOrigin;
        this.yOrigin = other.yOrigin;
        this.xCorner = other.xCorner;
        this.yCorner = other.yCorner;
        this.action = other.action;
    }

    public Action getAction() {
        return action;
    }

    public int getXCorner() {
        return xCorner;
    }

    public int getXOrigin() {
        return xOrigin;
    }

    public int getYCorner() {
        return yCorner;
    }

    public int getYOrigin() {
        return yOrigin;
    }

    public int getWidth() {
        return getXCorner() - getXOrigin();
    }

    public int getHeight() {
        return getYCorner() - getYOrigin();
    }

    public int getCenterX() {
        return getXOrigin() + getWidth() / 2;
    }

    public int getCenterY() {
        return getYOrigin() + getHeight() / 2;
    }

    public Point getCenterPoint() {
        int x;
        int y;
        synchronized (this) {
            x = this.getCenterX();
            y = this.getCenterY();
        }
        return new Point(x, y);
    }

    public Rectangle getRectangle() {
        return new Rectangle(xOrigin, yOrigin,
                getWidth(), getHeight());
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        final DTBoundingBoxEvent other = (DTBoundingBoxEvent) obj;
        if (this.action != other.action) return false;
        if (this.xOrigin != other.xOrigin) return false;
        if (this.yOrigin != other.yOrigin) return false;
        if (this.xCorner != other.xCorner) return false;
        if (this.yCorner != other.yCorner) return false;
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 67 * hash + this.action.hashCode();
        hash = 67 * hash + this.xOrigin;
        hash = 67 * hash + this.yOrigin;
        hash = 67 * hash + this.xCorner;
        hash = 67 * hash + this.yCorner;
        return hash;
    }

    @Override
    public String toString() {
        final StringBuffer buf = new StringBuffer();
        buf.append(super.toString());
        buf.append('[');
        buf.append("action=").append(action.name());
        buf.append(", x-origin=").append(xOrigin);
        buf.append(", y-origin=").append(yOrigin);
        buf.append(", x-corner=").append(xCorner);
        buf.append(", y-corner=").append(yCorner);
        buf.append(']');
        return buf.toString();
    }

    @Override
    public DTBoundingBoxEvent clone() {
        return new DTBoundingBoxEvent(this);
    }
}
